import { MathUtils } from '../../utilities/math-utils';
import { IWorld } from '../common/world.interface';
import { ColliderComponent } from '../components/collider.component';
import { CollisionEventComponent } from '../components/collision-event.component';
import { LocationComponent } from '../components/location.component';
import { System } from './system';

export class CollisionDetectionSystem extends System {
  onUpdate(world: IWorld, dt: number) {
    const entities = world.findEntitiesByComponents([LocationComponent, ColliderComponent]);
    if (entities.length < 2) {
      return;
    }

    const middleIndex = Math.floor(entities.length / 2);
    for (let i = 0; i < middleIndex; i++) {
      for (let j = entities.length - 1; j >= middleIndex; j--) {
        const beginEntity = entities[i];
        const endEntity = entities[j];

        const beginLocationComponent = world.findComponentByEntity(beginEntity, LocationComponent)!;
        const beginColliderComponent = world.findComponentByEntity(beginEntity, ColliderComponent)!;
        const endLocationComponent = world.findComponentByEntity(endEntity, LocationComponent)!;
        const endColliderComponent = world.findComponentByEntity(endEntity, ColliderComponent)!;

        const beginEvent = new CollisionEventComponent();
        const endEvent = new CollisionEventComponent();

        for (const beginConfig of beginColliderComponent.configs) {
          for (const endConfig of endColliderComponent.configs) {
            const beginLocation = beginLocationComponent.location.add(beginConfig.relativeLocation);
            const beginDimension = beginConfig.dimension;
            const endLocation = endLocationComponent.location.add(endConfig.relativeLocation);
            const endDimension = endConfig.dimension;

            if (!MathUtils.isIntersection(beginLocation, beginDimension, endLocation, endDimension)) {
              continue;
            }

            beginEvent.data.push({
              collidedEntity: endEntity,
              colliderConfig: endConfig,
            });

            endEvent.data.push({
              collidedEntity: beginEntity,
              colliderConfig: beginConfig,
            });
          }
        }

        if (beginEvent.data.length > 0) {
          world.attachComponentToEntity(CollisionEventComponent, beginEvent, beginEntity);
        }

        if (endEvent.data.length > 0) {
          world.attachComponentToEntity(CollisionEventComponent, endEvent, endEntity);
        }
      }
    }
  }
}
